package service

import (
	"saas-app/app/dao"
	"saas-app/app/define"
	"saas-app/app/model"
	"saas-app/library/response"
	"unicode/utf8"

	"github.com/gogf/gf/database/gdb"
	"github.com/gogf/gf/frame/g"
	"github.com/gogf/gf/os/gtime"
	"github.com/gogf/gf/util/gconv"
)

type coursePrice struct {
	KsValue float64
	CzValue float64
}

type StudentRepository interface {
	GetStudentList(school_id, campus_id, page, limit int) (studentList gdb.Result, total int)
	UpdateStudent(student_id uint, data map[string]interface{}) bool
	CreateStudent(student *model.Student) bool
	StudentCourselist(campus_id, student_id, page, limit int) ([]map[string]interface{}, int)
	Attendance(attendance *define.AttendanceParams) bool
}

type student struct{}

func StudentService() StudentRepository {
	return &student{}
}

func (s student) GetStudentList(school_id, campus_id, page, limit int) (studentList gdb.Result, total int) {

	if page <= 0 || limit <= 0 {
		panic("参数错误")
	}

	db := dao.Student.Where("school_id = ?", school_id).Where("campus_id = ?", campus_id)
	total, err := db.FindCount()

	if err != nil {
		panic(err)
	}

	studentList, err = db.Offset((page - 1) * limit).Limit(limit).FindAll()

	if err != nil {
		panic(err)
	}

	return studentList, total
}

func (s student) UpdateStudent(student_id uint, data map[string]interface{}) bool {

	if student_id <= 0 {
		response.Error("参数错误")
	}

	if data["student_name"] != nil && utf8.RuneCountInString(data["student_name"].(string)) > 20 {
		response.Error("参数错误 student_name")
	}

	if data["avatar"] != nil && utf8.RuneCountInString(data["avatar"].(string)) > 200 {
		response.Error("参数错误 avatar")
	}

	if data["address"] != nil && utf8.RuneCountInString(data["address"].(string)) > 50 {
		response.Error("参数错误 address")
	}

	if data["school_name"] != nil && utf8.RuneCountInString(data["school_name"].(string)) > 50 {
		response.Error("参数错误 school_name")
	}

	if data["birthday"] != nil && utf8.RuneCountInString(data["birthday"].(string)) > 20 {
		response.Error("参数错误 birthday")
	}

	if data["remark"] != nil && utf8.RuneCountInString(data["remark"].(string)) > 100 {
		response.Error("参数错误 remark")
	}

	if _, err := dao.Student.Where("id = ?", student_id).Update(data); err != nil {
		panic(err)
	} else {
		return true
	}

}

func (s student) CreateStudent(student *model.Student) bool {

	_, err := dao.Student.Save(student)

	if err != nil {
		panic(err)
	}

	return true
}

func (s student) StudentCourselist(campus_id, student_id, page, limit int) ([]map[string]interface{}, int) {

	courseId, err := dao.CourseMember.Where("campus_id", campus_id).Where("student_id", student_id).Array("course_id")

	if err != nil {
		panic(err)
	}

	db := dao.Course.WhereIn("course.id", courseId).LeftJoin("subject", "course.subject_id = subject.id")

	total, _ := db.Count()

	result, err := db.Offset((page-1)*limit).Limit(limit).Fields("course.*", "subject.subject_name").All()

	if err != nil {
		panic(err)
	}

	courseList := result.List()

	for _, v := range courseList {
		start := gtime.New(v["start_time"].(string)).Timestamp()
		end := gtime.New(v["end_time"].(string)).Timestamp()
		now := int64(gtime.Timestamp())

		if start > now {
			v["status"] = 1
		}

		if start < now && end >= now {
			v["status"] = 2
		}

		if end < now {
			v["status"] = 3
		}
	}

	return courseList, total
}

/**
考勤
*/
func (s student) Attendance(attendance *define.AttendanceParams) bool {
	// 1. 先在考勤记录表中查询 是否有考勤记录
	newAttendance := model.Attendance{}

	dao.Attendance.Where("student_id", attendance.StudentId).Where("course_id", attendance.CourseId).Struct(&newAttendance)

	tx, err := g.DB().Begin()

	if err != nil {
		panic(err)
	}

	// 2. 考勤不存在，新增
	if newAttendance.Id == 0 {

		// 获取学员卡类型
		card_type := getCardType(attendance.CardId)
		// 获取课程价格
		course_price := getCoursePrice(attendance.CourseId)
		// 获取课消金额
		kx := getKxValue(course_price, card_type)
		// 赋值上次课消
		var last_kx float64 = 0
		if attendance.Deduct == 1 {
			last_kx = kx
		}
		// 新建考勤记录
		newAttendance.SchoolId = uint(attendance.SchoolId)
		newAttendance.CampusId = uint(attendance.CampusId)
		newAttendance.StudentId = uint(attendance.StudentId)
		newAttendance.CourseId = uint(attendance.CourseId)
		newAttendance.Status = gconv.String(attendance.Status)
		newAttendance.CardId = uint(attendance.CardId)
		newAttendance.Kx = kx
		newAttendance.LastKx = last_kx
		newAttendance.OperatorId = 1
		if _, err := dao.Attendance.Data(newAttendance).Save(); err != nil {
			tx.Rollback()
			panic(err)
		}

		// 扣除学员卡 余额
		student_card := model.StudentCard{}
		dao.StudentCard.Where("id", attendance.CardId).Scan(&student_card)
		student_card.Residue = student_card.Residue - last_kx
		if _, err := dao.StudentCard.Data(student_card).Where(student_card.Id).Update(); err != nil {
			tx.Rollback()
			panic(err)
		}

		tx.Commit()
		return true

	} else {
		// 3. 考勤存在，修改
		studentCardModel := model.StudentCard{}
		dao.StudentCard.Where("id", attendance.CardId).Struct(&studentCardModel)

		if err != nil {
			panic(err)
		}

		// 先把上次扣除的加上
		if _, err = dao.StudentCard.Where("id", attendance.CardId).Increment("residue", newAttendance.LastKx); err != nil {
			tx.Rollback()
			panic(err)
		}

		var last_kx float64 = 0
		if attendance.Deduct == 1 {
			// 更新学员卡余额
			if _, err = dao.StudentCard.Where("id", attendance.CardId).Decrement("residue", newAttendance.Kx); err != nil {
				tx.Rollback()
				panic(err)
			}

			last_kx = newAttendance.Kx
		}

		// 更新考勤last_kx
		newAttendance.LastKx = last_kx
		newAttendance.Status = gconv.String(attendance.Status)
		newAttendance.OperatorId = 0

		if _, err := dao.Attendance.Data(newAttendance).Where("id", newAttendance.Id).Update(); err != nil {
			tx.Rollback()
			panic(err)
		}

		tx.Commit()
		return true
	}
}

func getCardType(card_id int) int {

	result, err := dao.StudentCard.Where("student_card.id", card_id).LeftJoin("card", "student_card.card_type_id = card.id").Fields("card.card_type").One()

	if err != nil {
		panic(err)
	}

	if result.IsEmpty() {
		response.Error("学员卡不存在")
	}

	card_type := gconv.Int(result.GMap().Get("card_type"))

	return card_type
}

func getCoursePrice(course_id int) *coursePrice {

	result, err := dao.Course.Where("course.id = ?", course_id).LeftJoin("subject", "course.subject_id = subject.id").Fields("subject.ks_value", "subject.cz_value").One()

	if err != nil {
		panic(err)
	}

	if result.IsEmpty() {
		response.Error("学员卡不存在")
	}

	course_price := coursePrice{}

	result.Struct(&course_price)

	return &course_price
}

func getKxValue(cp *coursePrice, card_type int) float64 {
	// 课时卡
	if card_type == 1 {
		return cp.KsValue
	}
	// 储值卡
	if card_type == 2 {
		return cp.CzValue
	}

	return 0
}
